
print('-----------------------------------------------------')
print('client terminal online moniter svr ')

print('-----------------------------------------------------')
'''
参考文档：
    https://blog.csdn.net/daizikui/article/details/135258421?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-2-135258421-blog-140322826.235%5Ev43%5Epc_blog_bottom_relevance_base4&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-2-135258421-blog-140322826.235%5Ev43%5Epc_blog_bottom_relevance_base4&utm_relevant_index=5
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple apscheduler
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple fastapi 
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple uvicorn
'''
import time
from typing import Union
from apscheduler.schedulers.background import BackgroundScheduler
from fastapi import FastAPI
import uvicorn
from contextlib import asynccontextmanager
import json
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart

class TOnlineSvr:
    def __init__(self):
        self.config = {
            "svrCode":"online-monitor-svr",
            "mailNotify":{
                "sendMail":"277062751@qq.com",
                "sendMailPassword":"123456",
                "stmpSvr":"smtp.qq.com",
                "stmpPort":587,
                "recMailList":[
                    "zp111111mm@163.com",
                    "277062751@qq.com"
                ]
            },
            "terminals":[
                { "code":"xinyueyang" , "label":"新跃洋" , "threshold":"10" },
                { "code":"cz645" , "label":"645电表" , "threshold":"60" },
                { "code":"fy101" , "label":"凤阳101监测" , "threshold":"60" },
            ]
        }
        self.terminals={}
    def load(self):
        try:
            for terConfig in self.config['terminals']:
                terCode = terConfig['code']
                if terCode not in self.terminals.keys():
                    ter = {
                        "code": terCode ,
                        'terName': terConfig['label'],
                        "threshold" : int(terConfig['threshold'] ),
                        "lastTime" : time.time(),
                        "online": 1,
                        "label": terCode +' - '+ terConfig['label']
                    }
                    self.terminals[terCode] = ter;
                    print('load terminal ', terConfig)
        except Exception as er:
            print(er)
    def check(self):
        try:
            for ter in self.terminals.values():
                dltTime = time.time() - ter['lastTime']
                threshold = ter['threshold']
                if dltTime> threshold and ter['online']==1 :
                    ter['online'] = 0
                    self.notify(ter, 0)
                elif dltTime <= threshold and ter['online']==0 :
                    ter['online'] = 1
                    self.notify(ter, 1)
        except Exception as er:
            print(er)
    def regist(self, code):
        res = {
            "terminalCode": code ,
            "success": 0
        }
        try:
            if code in self.terminals.keys():
                ter = self.terminals[code]
                ter["lastTime"] = time.time()
                res['success'] = 1
                res['time'] = time.time()
        except Exception as er:
            print(er)
        return  res
    def notify(self, terminal, status):
        try:
            print('terminal online status changed:' , json.dumps(terminal) , status)

            sender_email = self.config['mailNotify']['sendMail']
            receiver_emails = self.config['mailNotify']['recMailList']
            password = self.config['mailNotify']['sendMailPassword']
            stmpSvr= self.config['mailNotify']['stmpSvr']
            stmpPort= self.config['mailNotify']['stmpPort']
            terStatus=[
                "远程终端 [ "+ terminal['label'] +" ] 离线！",
                "远程终端 [ "+ terminal['label'] +" ] 上线！"
            ]
            subject = terStatus[status]
            server = None
            try:
                # 连接到 SMTP 服务器
                server = smtplib.SMTP(stmpSvr, stmpPort)
                server.starttls()  # 启用安全传输
                server.login(sender_email, password)
                for receiver_email in receiver_emails:
                    # 创建邮件对象
                    message = MIMEMultipart()
                    message["From"] = sender_email
                    message["To"] = receiver_email
                    message["Subject"] = subject

                    # 邮件正文
                    body = subject
                    message.attach(MIMEText(body, "plain"))
                    # 发送邮件
                    server.sendmail(sender_email, receiver_email, message.as_string())
                    print("Email sent successfully!")
            except Exception as e:
                print(f"Error: {e}")
            finally:
                if server!=None:
                    try:
                        server.quit()
                    except Exception as err:
                        print(err)
        except Exception as er:
            print(er)
onlineSvr = TOnlineSvr()
onlineSvr.load()

data_task = BackgroundScheduler()
task_id = 'data_task_1'

@asynccontextmanager
async def lifespan(app: FastAPI):
    # 星期2——6 5:30 执行一次
    # scheduler.add_job(func=task_function, trigger="cron", day_of_week='1,2,3,4,6', hour=5,minute=30)
    data_task.add_job(func=task_function, trigger="interval",  seconds=5,id=task_id)
    data_task.start()
    print("启动前执行")
    yield
    print("关闭后前执行")
def task_function():
    onlineSvr.check()
    print(f"Current Time: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}")

app = FastAPI(lifespan=lifespan)
@app.get("/scheduler/stop")
def stop():
    data_task.pause_job(task_id)
    print(task_id + ' is stop')
    return task_id + ' is stop'
@app.get("/scheduler/start")
def start():
    data_task.resume_job(task_id)
    print(task_id + ' is start')
    return task_id + ' is start'

@app.get("/regist/online/{code}")
async def regist(code:str):
    try:
        res = onlineSvr.regist(code)
        return res
    except Exception as er:
        print(er)


# 第二种启动方式：
if __name__ == '__main__':
    uvicorn.run(app="main:app", host="localhost", port=8000)